import 'dart:async';

import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:im_app/im/dao/ImLoginDao.dart';
import 'package:im_app/im/socket/dto/business/PullData.dart';
import 'package:im_app/im/socket/exception/RpcException.dart';
import 'package:im_app/im/util/DbUtil.dart';
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';

import '../../pojo/Enums.dart';
import '../../pojo/ImPojo.dart';
import '../../service/LoginService.dart';
import '../../service/SynDataService.dart';
import '../../socket/dto/business/Login.dart';

final class LoginCubit extends Bloc<LoginEvent, LoginState> {
  LoginCubit() : super(LoginState.loading()) {
    on<LoginSelectLoginType>((event, emit){
      _selectLoginType(state, event.loginType);
    });
    on<LoginSelectUser>((event, emit) {
      _selectUser(state.logins, event.imLogin);
    });
    on<LoginUserChange>((event, emit) {
      _nameChange(state.logins, event.name);
    });
    on<LoginPasswordChange>((event, emit) {
      LoginState newState = state.copy(password: event.password);
      emit(newState);
    });
    on<LoginSeePassword>((event, emit) {
      LoginState newState = this.state.copy(isCanSeePassword: event.isCanSeePassword);
      emit(newState);
    });
    on<LoginSubmit>((event, emit) {
      loginSubmit(event.userId, event.password, event.tenantCode, 'android-flutter');
    });
    on<LoginResetEvent>((event, emit) {
      _loginReset(state);
    });
  }

  final _logger = Logger(
    printer: PrettyPrinter(),
  );

  Future<LoginType> loadData() async {
    _logger.i("login begin load data!");
    var loginDao = ImLoginDao();
    List<ImLogin> result = await loginDao.getLogins();
    ImLogin? lastedLogin = await loginDao.getLoginForLasted();
    LoginType loginType = await _selectUser(result, lastedLogin);
    return loginType;
  }

  Future<bool> loginSubmit(String userId, String password, String tenantCode, String machineCode) async {
    var newState = state.copy();
    newState.isError = false;
    newState.msg = '正在登录中';
    newState.isLogining = true;
    emit(newState);

    try {
      LoginReq loginReq = LoginReq(userId: userId, password: password, machineCode: machineCode,
          tenantCode: tenantCode, terminalType: TerminalType.android.name);
      LoginService loginService = LoginService();
      await loginService.login(loginReq, LoginType.password);

      newState.isLogining = false;

      bool isSlidePasswordSetting = await checkSlidePasswordIsSetting(state.currentImLogin);
      if (isSlidePasswordSetting) {
        LoginState newState = state.copy(loginSuccessRouter: 'main');
        emit(newState);
        return true;
      } else {
        LoginState newState = state.copy(loginSuccessRouter: 'slide');
        emit(newState);
        return true;
      }
    } catch(error, strackTrace) {
      _logger.e('登录失败', error: error, stackTrace: strackTrace);
      if(error is RpcException) {
        var exception = error as RpcException;
        LoginState newState = state.copy(msg: exception.toString(), isError: true, isLogining: false);
        emit(newState);
      } else {
        LoginState newState = state.copy(msg: '登录失败', isError: true, isLogining: false);
        emit(newState);
      }
      return false;
    }
  }

  Future<bool> loginBySlide(String userId, String password, String tenantCode, String machineCode) async {
    try {
      LoginReq loginReq = LoginReq(userId: userId, password: password, machineCode: machineCode,
          tenantCode: tenantCode, terminalType: TerminalType.android.name);
      LoginService loginService = LoginService();
      await loginService.login(loginReq, LoginType.slidePassword);
    } on TimeoutException catch(error) {
      emit(LoginState.failure("链接超时"));
    } catch(error) {
      emit(LoginState.failure(error.toString()));
    }
    return true;
  }

  void _loginReset(LoginState oldState) {
    emit(LoginState.success(oldState.logins, oldState.currentImLogin, oldState.loginType, oldState.popupMoreIcon, oldState.name));
  }

  void _selectLoginType(LoginState loginState, LoginType loginType) {
    String popupMoreIcon = '';
    if (loginType == LoginType.password) {
      popupMoreIcon = 'assets/svg/password.svg';
    } else if (loginType == LoginType.slidePassword) {
      popupMoreIcon = 'assets/svg/pattern-lock.svg';
    } else if (loginType == LoginType.scanLock) {
      popupMoreIcon = 'assets/svg/qrcode.svg';
    } else {
      popupMoreIcon = 'assets/svg/qrcode.svg';
    }
    LoginState newState = loginState.copy(loginType: loginType, popupMoreIcon: popupMoreIcon);
    emit(newState);
  }

  Future<LoginType> _selectUser(List<ImLogin> imLogins, ImLogin? imLogin) async {
    LoginType loginType = LoginType.password;
    if (imLogin != null) {
      loginType = imLogin!.loginType??LoginType.password;
      bool isSlideLogin = await checkSlidePasswordIsSetting(imLogin!);
      // if (isSlideLogin) {
      //   loginType = LoginType.slidePassword;
      // }
    }

    emit(LoginState.success(imLogins, imLogin, loginType, 'assets/svg/qrcode.svg', imLogin?.userId));
    return loginType;
  }

  Future<LoginType> _nameChange(List<ImLogin> imLogins, String name) async {
    for(var imLogin in imLogins) {
      if (imLogin.userId == name) {
        emit(LoginState.success(imLogins, imLogin, LoginType.password, 'assets/svg/password.svg', name));
        return LoginType.password;
      }
    }
    emit(LoginState.success(imLogins, null, LoginType.password, 'assets/svg/password.svg', name));
    return LoginType.password;
  }

  // 判断滑屏密码是否设置
  Future<bool> checkSlidePasswordIsSetting(ImLogin? imLogin) async {
    return true;
    // if (imLogin == null) return false;
    // final SharedPreferences prefs = await SharedPreferences.getInstance();
    // bool? isSetting = prefs.getBool(ImConfig.IM_PATTERN_LOCK_SETTING + imLogin.userId);
    // if (isSetting == null || !isSetting) {
    //   return false;
    // }
    // if (!prefs.containsKey(ImConfig.IM_PATTERN_LOCK_USERID + imLogin.userId)) return false;
    // if (!prefs.containsKey(ImConfig.IM_PATTERN_LOCK_PASSWORD + imLogin.userId)) return false;
    // return true;
  }
}

final class LoginState extends Equatable {
  final LoadingState state;
  final List<ImLogin> logins;
  LoginType loginType;
  ImLogin? currentImLogin = null;
  String name;
  String popupMoreIcon;
  String msg;
  bool isCanSeePassword = true;
  String password = "";
  bool isLogining = false;
  bool isError = false;
  String loginSuccessRouter;

  LoginState._({
    this.state = LoadingState.loading,
    this.logins = const <ImLogin>[],
    this.loginType = LoginType.password,
    this.currentImLogin = null,
    this.name = '',
    this.password = '',
    this.isCanSeePassword = true,
    this.isLogining = false,
    this.isError = false,
    this.popupMoreIcon = 'assets/svg/qrcode.svg',
    this.msg = '',
    this.loginSuccessRouter = '',
  });

  LoginState.loading() : this._();

  LoginState.success(List<ImLogin> logins, ImLogin? lastedLogin, LoginType loginType, String popupMoreIcon,String? name)
      : this._(state: LoadingState.success, logins: logins, currentImLogin: lastedLogin,
      loginType: loginType, popupMoreIcon: popupMoreIcon, name: name??'');

  LoginState.failure(String msg) : this._(state: LoadingState.failure, msg: msg, isError: true);

  LoginState copy({ List<ImLogin>? logins, ImLogin? lastedLogin, LoginType? loginType, String? popupMoreIcon,
      String? name, String? password, bool? isError, String? msg, String? loginSuccessRouter, bool? isLogining,
      bool? isCanSeePassword, LoadingState? state }) {
    return LoginState._(
      state: state ?? this.state,
      logins: logins ?? this.logins,
      loginType: loginType ?? this.loginType,
      currentImLogin: lastedLogin ?? this.currentImLogin,
      name: name ?? this.name,
      password: password ?? this.password,
      isCanSeePassword: isCanSeePassword ?? this.isCanSeePassword,
      isLogining: isLogining ?? this.isLogining,
      isError: isError ?? this.isError,
      popupMoreIcon: popupMoreIcon ?? this.popupMoreIcon,
      msg: msg ?? this.msg,
      loginSuccessRouter: loginSuccessRouter ?? this.loginSuccessRouter,
    );
  }

  @override
  List<Object?> get props => [state, logins, loginType, currentImLogin, popupMoreIcon, msg, name, password,
    isCanSeePassword, isLogining, isError, loginSuccessRouter];
}

abstract class LoginEvent {}
class LoginSelectLoginType extends LoginEvent {
  LoginType loginType;
  LoginSelectLoginType(this.loginType);
}

class LoginSelectUser extends LoginEvent {
  ImLogin imLogin;
  LoginSelectUser(this.imLogin);
}

class LoginUserChange extends LoginEvent {
  String name;
  LoginUserChange(this.name);
}
class LoginPasswordChange extends LoginEvent {
  String password;
  LoginPasswordChange(this.password);
}
class LoginSeePassword extends LoginEvent {
  bool isCanSeePassword;
  LoginSeePassword(this.isCanSeePassword);
}
class LoginSubmit extends LoginEvent {
  String userId;
  String password;
  String tenantCode;
  LoginSubmit(this.userId, this.password, this.tenantCode);
}
class LoginResetEvent extends LoginEvent {}